/**
  ******************************************************************************
  * @file    Project/STM32F10x_StdPeriph_Template/main.c 
  * @author  MCD Application Team
  * @version V3.5.0
  * @date    08-April-2011
  * @brief   Main program body
  ******************************************************************************
  * @attention
  *
  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
  *
  * <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
  ******************************************************************************
  */  

/* Includes ------------------------------------------------------------------*/
#include <stdio.h>
#include <string.h>
#include "led.h"
#include "spi_flash.h"
#include "usart.h"
#include "usart_stdio.h"
#include "base_timer.h"
#include "keyboard.h"
#include "oled_softspi.h"
#include "RTC.h"

void InitializeSPIFlash(void);
void TestReadFlash(void);
void TestWriteFlash(void);
void ConfigRTC(void);
void USARTReceiveProc(USART_INT_REASON eReason, uint8_t uiReceiveData);
void KeyEventProc(uint16_t uiKeyCode, KEY_EVENT eEvent);
void TimerEventProc(void);

#define	TEST_DATA_LEN		(64)
uint8_t		pTestReadBuffer[TEST_DATA_LEN] = {0x00};
uint8_t		pTestWriteBuffer[TEST_DATA_LEN] = {0x00};
char		pUSART1ReceiveBuffer[TEST_DATA_LEN+1] = {0x00};
size_t		sRevIdx=0;
bool __IO	bReceived = false;

int main(void)
{
	/* Initialize usart 1 for stdio. */
	USART_Stdio_Initialize(115200);
	printf("Stand IO initialized.\r\n");
	USART1_ConfigReceiveInterrupt(USARTReceiveProc, 2, 2);
	USART_ActiveInterrupt(USART1, true);
	bReceived = false;
	
	/* Initialize LED and turn off. */
	LED_Initialize();
	printf("LED initialized.\r\n");
	LED_Off();
	
	/* Initialize RTC and interrupt. */
	RTC_Initialize();
	printf("RTC initialized.\r\n");
	ConfigRTC();
	
	/* Initialize SPI flash */
	InitializeSPIFlash();
	
	/* Initialize base timer. */
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
	BASE_TIMER_Initialize(TIM3, 499, 7199);
	TIM3_ConfigReceiveInterrupt(TimerEventProc, 2, 2);
	BASE_TIMER_ActiveInterrupt(TIM3, true);
	printf("General timer initialized.\r\n");
	
	/* Initialize key board. */
	KB_Initialize();
	KB_RegisterEventProc(KeyEventProc);
	printf("Key board initialized.\r\n");

	SSD1306_Initialize();
	SSD1306_Fill(0xF0);
	printf("OLED screen initialized.\r\n");

	while(1)
	{
		if(true == bReceived)
		{
			bReceived = false;
			puts(pUSART1ReceiveBuffer);
			sRevIdx = 0;
			pUSART1ReceiveBuffer[sRevIdx] = '\0';
			USART_ActiveInterrupt(USART1, true);
		}
		
		if(KEY_STATE_DOWN == KB_CheckKeyState(KEY_CODE_F1))
		{
			printf(" F1 is down.");
		}
		if(KEY_STATE_DOWN == KB_CheckKeyState(KEY_CODE_F2))
		{
			printf(" F2 is down.");
		}
	}
}

void USARTReceiveProc(USART_INT_REASON eReason, uint8_t uiReceiveData)
{
	if(eReason == USART_INT_REASON_IDLE)
	{
		USART_ActiveInterrupt(USART1, false);
		pUSART1ReceiveBuffer[sRevIdx] = '\0';
		bReceived = true;
	}
	else if(eReason == USART_INT_REASON_REV)
	{
		if(sRevIdx < TEST_DATA_LEN)
		{
			pUSART1ReceiveBuffer[sRevIdx++] = uiReceiveData;
		}
	}
}

void InitializeSPIFlash(void)
{
	uint32_t		uiChipID = 0;
	
	printf("Configuration SPI flash.\r\n");
	SPI_FLASH_Initialize();
	uiChipID = SPI_FLASH_ReadID();
	printf("Flash chip ID is 0x%04X.\r\n", uiChipID);
}


void TestReadFlash(void)
{
	int iRowIdx, iByteIdx;
	
	//Read data.
	printf("Read %d bytes flash data form 0x00000000.\r\n", TEST_DATA_LEN);
	SPI_FLASH_ReadData(0x00000000, pTestReadBuffer, TEST_DATA_LEN);
	
	for(iRowIdx=0; iRowIdx<4; iRowIdx++)
	{
		for(iByteIdx=0; iByteIdx<16; iByteIdx++)
		{
			printf("0x%02X, ", pTestReadBuffer[iRowIdx*16+iByteIdx]);
		}
		putchar('\r');
		putchar('\n');
	}
	
}

void TestWriteFlash(void)
{
	int iRowIdx, iByteIdx;
	
	//Read data.
	printf("Write %d bytes flash data form 0x00000000.\r\n", TEST_DATA_LEN);
	
	for(iRowIdx=0; iRowIdx<4; iRowIdx++)
	{
		for(iByteIdx=0; iByteIdx<16; iByteIdx++)
		{
			pTestWriteBuffer[iRowIdx*16+iByteIdx] = (((iRowIdx<<4) & 0xF0) | (iByteIdx & 0x0F));
		}
	}
	SPI_FLASH_WriteData(0x00000000, pTestWriteBuffer, TEST_DATA_LEN);
}

void ConfigRTC(void)
{
	RTC_CALENDAR_STRUCT			stTime;
	
	stTime.tm_year = 2020;
	stTime.tm_mon = 1;
	stTime.tm_mday = 8;
	stTime.tm_hour = 22;
	stTime.tm_min = 48;
	stTime.tm_sec = 30;
	
	RTC_UpdateCalendar(&stTime);
}

void KeyEventProc(uint16_t uiKeyCode, KEY_EVENT eEvent)
{
	if(KEY_EVENT_DOWN == eEvent)
	{
		printf("Key 0x%02X is down.", uiKeyCode);
		printf("\r\n");
	}
}

void TimerEventProc(void)
{
	BASE_TIMER_ActiveInterrupt(TIM3, false);
	KB_Scan();
	LED_Reverse();
	BASE_TIMER_ActiveInterrupt(TIM3, true);
}
